home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir24 / jnos110g.zip / MAILBOX.C < prev    next >
C/C++ Source or Header  |  1994-08-26  |  42KB  |  1,560 lines

  1. /* NOTE: because of size, the previous 'mailbox.c' and 'mailbox2.c'
  2.  * have been split in 5 parts:
  3.  * mboxcmd.c, containing the 'mbox' subcommands,
  4.  * mailbox.c, containing general mailbox user commands,
  5.  * mboxfile.c, containing file mailbox user commands,
  6.  * mboxmail.c, containing mail mailbox user commands, and
  7.  * mboxgate.c, containing gateway mailbox user commands.
  8.  * 940215 - WG7J
  9.  */
  10.   
  11. /* There are only two functions in this mailbox code that depend on the
  12.  * underlying protocol, namely mbx_getname() and dochat(). All the other
  13.  * functions can hopefully be used without modification on other stream
  14.  * oriented protocols than AX.25 or NET/ROM.
  15.  *
  16.  * SM0RGV 890506, most work done previously by W9NK
  17.  *
  18.  *** Changed 900114 by KA9Q to use newline mapping features in stream socket
  19.  *      interface code; everything here uses C eol convention (\n)
  20.  *
  21.  *      Numerous new commands and other changes by SM0RGV, 900120
  22.  *
  23.  * Gateway function now support outgoing connects with the user's call
  24.  * with inverted ssid. Users can connect to system alias as well...
  25.  * See also several mods in socket.c,ax25.c and others
  26.  * 11/15/91, WG7J/PA3DIS
  27.  *
  28.  * Userlogging, RM,VM and KM commands, and R:-line interpretation
  29.  * added 920307 and later, Johan. K. Reinalda, WG7J/PA3DIS
  30.  *
  31.  * Inactivity timeout-disconnect added 920325 and later - WG7J
  32.  *
  33.  */
  34. #include <time.h>
  35. #include <ctype.h>
  36. #ifdef MSDOS
  37. #include <alloc.h>
  38. #endif
  39. #ifdef  UNIX
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. #endif
  43. #include "global.h"
  44. #ifdef MAILBOX
  45. #include "timer.h"
  46. #include "proc.h"
  47. #include "socket.h"
  48. #include "usock.h"
  49. #include "session.h"
  50. #include "smtp.h"
  51. #include "dirutil.h"
  52. #include "telnet.h"
  53. #include "ftp.h"
  54. #include "ftpserv.h"
  55. #include "commands.h"
  56. #include "netuser.h"
  57. #include "files.h"
  58. #include "bm.h"
  59. #include "pktdrvr.h"
  60. #include "ax25.h"
  61. #include "mailbox.h"
  62. #include "ax25mail.h"
  63. #include "nr4mail.h"
  64. #include "cmdparse.h"
  65. #include "mailfor.h"
  66. #include "mailutil.h"
  67. #include "index.h"
  68.   
  69. struct mbx *Mbox;
  70. int BbsUsers;
  71. int Totallogins;
  72. extern int MbShowAliases;
  73.   
  74. #ifdef RLOGINSERVER
  75. static char DFAR RLoginbanner[] = "\nRemote Login at %s - %s\n\n";
  76. #endif
  77. char Loginbanner[] = "\nJNOS (%s)\n\n";
  78. char Mbwelcome[] = "\nWelcome %s,\n";
  79. char Mbbanner[] = "to the %s TCP/IP Mailbox (JNOS %s).\n";
  80. char CurUsers[] = "Currently %d user%s.\n";
  81.   
  82. #if defined MAILCMDS || defined FILECMDS
  83. char Howtoend[] = "End with /EX or ^Z in first column (^A aborts):\n";
  84. char MsgAborted[] = "Msg aborted\n";
  85. #endif
  86.   
  87. #ifdef MAILCMDS
  88. char MbCurrent[] = "Current msg# %d.\n";
  89. #endif
  90.   
  91. char Mbmenu[] = "?,"
  92. #ifdef MAILCMDS
  93. "A,"
  94. #endif
  95. "B,"
  96. #ifdef GATECMDS
  97. #if defined NETROM || defined AX25
  98. "C,"
  99. #endif
  100. #endif
  101. #ifdef CONVERS
  102. "CONV,"
  103. #endif
  104. #ifdef FILECMDS
  105. "D,"
  106. #endif
  107. #ifdef GATECMDS
  108. "E,"
  109. #endif
  110. #ifdef FOQ_CMDS
  111. "F,"
  112. #endif
  113. "H,I,IH,IP,J,"
  114. #ifdef MAILCMDS
  115. "K,L,"
  116. #endif
  117. "M,"
  118. #if defined GATECMDS && defined NETROM
  119. "N,NR,"
  120. #endif
  121. #if defined FOQ_CMDS && defined TTYLINKSERVER
  122. "O,"
  123. #endif
  124. #ifdef GATECMDS
  125. "P,PI,"
  126. #endif
  127. #if defined FOQ_CMDS && defined CALLCLI
  128. "Q,"
  129. #endif
  130. #ifdef MAILCMDS
  131. "R,S,"
  132. #endif
  133. #ifdef GATECMDS
  134. "T,"
  135. #endif
  136. #ifdef FILECMDS
  137. "U,"
  138. #endif
  139. #ifdef MAILCMDS
  140. "V,"
  141. #endif
  142. #ifdef FILECMDS
  143. "W,"
  144. #endif
  145. "X"
  146. #ifdef FILECMDS
  147. ",Z"
  148. #endif
  149. " >\n";
  150.   
  151. extern char Mbnrid[];
  152.   
  153. char Longmenu[] =
  154. #ifdef MAILCMDS
  155. "Mail   : Area Kill List Read Send Verbose\n"
  156. #endif
  157.   
  158. #ifdef GATECMDS
  159.   
  160. "Gateway:"
  161. #if defined AX25 || defined NETROM
  162. " Connect"
  163. #endif
  164. " Escape"
  165. #ifdef NETROM
  166. " Nodes NRroute"
  167. #endif
  168. #ifdef AX25
  169. " Ports"
  170. #endif
  171. " PIng Telnet\n"
  172.   
  173. #endif /* GATECMDS */
  174.   
  175. #ifdef FILECMDS
  176. "File   : Download Upload What Zap\n"
  177. #endif
  178.   
  179. "General: ?-Help Bye"
  180. #ifdef CONVERS
  181. " CONVers"
  182. #endif
  183. #ifdef FOQ_CMDS
  184. " Finger"
  185. #endif
  186. " Help Info IHeard\n"
  187. "         IProute"
  188. #ifdef AX25
  189. " Jheard"
  190. #endif
  191. " Mbox"
  192. #if defined FOQ_CMDS && defined TTYLINKSERVER
  193. " Operator"
  194. #endif
  195. #if defined FOQ_CMDS && defined CALLCLI
  196. " Query"
  197. #endif
  198. " Xpert\n\n";
  199.   
  200.   
  201. /* This is called by the finger-daemon */
  202. void
  203. listusers(s)
  204. int s;
  205. {
  206.     int outsave;
  207.     struct mbx m;
  208.   
  209.     m.privs = 0;
  210.     m.stype = ' ';
  211.   
  212. #ifdef notdef
  213.     usputs(s,"\nCurrent remote users:\n");
  214. #endif
  215.     outsave = Curproc->output;
  216.     Curproc->output = s;
  217.     dombusers(0,NULLCHARP,&m);
  218.     Curproc->output = outsave;
  219. }
  220.   
  221. struct mbx *
  222. newmbx()
  223. {
  224.     struct mbx *m,*new;
  225.   
  226.     if((new = (struct mbx *) callocw(1,sizeof(struct mbx))) == NULLMBX)
  227.         return NULLMBX;
  228.     BbsUsers++;
  229.     /* add it the list */
  230.     if((m=Mbox) == NULLMBX)
  231.         Mbox = new;
  232.     else {
  233.         while(m->next)
  234.             m=m->next;
  235.         m->next = new;
  236.     }
  237.     return new;
  238. }
  239.   
  240. static int
  241. mbx_getname(m)
  242. struct mbx *m;
  243. {
  244.     char *cp;
  245. #ifdef notdef
  246.     FILE *tfp;
  247. #endif
  248.     union sp sp;
  249.     char tmp[MAXSOCKSIZE];
  250.     int len = MAXSOCKSIZE;
  251.     int anony = 0;
  252.     int oldmode;
  253.     int founddigit=0;
  254.     int count=0;
  255. #ifdef AX25
  256.     int32 flags;
  257.     int ax_25 = 0;
  258.     struct usock *up;
  259. #endif
  260.   
  261.     sp.p = tmp;
  262.     sp.sa->sa_family = AF_LOCAL;    /* default to AF_LOCAL */
  263.     getpeername(m->user,tmp,&len);
  264.     m->family = sp.sa->sa_family;
  265.     m->path = mallocw(MBXLINE);
  266.     /* This is one of the two parts of the mbox code that depends on the
  267.      * underlying protocol. We have to figure out the name of the
  268.      * calling station. This is only practical when AX.25 or NET/ROM is
  269.      * used. Telnet users have to identify themselves by a login procedure.
  270.      */
  271.     switch(sp.sa->sa_family){
  272. #ifdef  AX25
  273.         case AF_AX25:
  274.         /* If this is not to the convers call, and this port is
  275.          * set for NO_AX25, then disconnect ! - WG7J
  276.          */
  277.             if((m->type != CONF_LINK) && ((up = itop(m->user)) != NULLUSOCK) ) {
  278.                 if((flags=up->cb.ax25->iface->flags) & NO_AX25)
  279.                     return -1;
  280.             }
  281.             ax_25 = 1;
  282.         /* note fallthrough */
  283.         case AF_NETROM:
  284.         /* NETROM and AX25 socket address structures are "compatible" */
  285.         /* Save user call, in case user wants to use gateway function */
  286.             memcpy(m->call,sp.ax->ax25_addr,AXALEN);
  287.             m->call[ALEN] &= 0xfc;/*Make sure E-bit isn't set !*/
  288.             pax25(m->name,sp.ax->ax25_addr);
  289.             cp = strchr(m->name,'-');
  290.             if(cp != NULLCHAR)                      /* get rid of SSID */
  291.                 *cp = '\0';
  292.         /* SMTP wants the name to be in lower case */
  293.             cp = m->name;
  294.             while(*cp){
  295.                 if(isupper(*cp))
  296.                     *cp = tolower(*cp);
  297.                 ++cp;
  298.             }
  299.             anony = 1;
  300.         /* Try to find the privileges of this user from the userfile */
  301.             if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,&anony)) == -1){
  302.                 m->privs = 0;
  303.                 free(m->path);
  304.                 m->path = NULLCHAR;
  305.             }
  306.             if(m->privs & EXCLUDED_CMD)
  307.                 return -1;
  308.             if(ax_25)
  309.                 if(((flags & USERS_ONLY) && (m->privs & IS_BBS)) ||
  310.                     ((flags & BBS_ONLY) && !(m->privs & IS_BBS)) ||
  311.                     ((flags & SYSOP_ONLY) && !(m->privs & SYSOP_CMD)))
  312.                     return -1;
  313.             return 0;
  314. #endif
  315.         case AF_LOCAL:
  316.         case AF_INET:
  317.             m->state = MBX_LOGIN;
  318. #ifdef RLOGINSERVER
  319.             if(m->type == RLOGIN_LINK)
  320.                tprintf(RLoginbanner,Hostname,Version);
  321.             else {
  322. #endif
  323.             tprintf(Loginbanner,Hostname);
  324.             if(Mtmsg != NULLCHAR)
  325.                 tputs(Mtmsg);
  326. #ifdef RLOGINSERVER
  327.             }
  328. #endif
  329.             for(;;){
  330.             /* Maximum of 3 tries - WG7J */
  331.                 if(count++ == 3)
  332.                     return -1;
  333.                 oldmode = sockmode(m->user,SOCK_ASCII);
  334.                 tputs("login: ");
  335.                 usflush(m->user);
  336.                 if(mbxrecvline(m) == -1)
  337.                     return -1;
  338.                 if(*m->line == 4) /* Control-d */
  339.                     return -1;
  340.                 if(*m->line == '\0')
  341.                     continue;
  342.             /* Chop off after name lenght */
  343.                 m->line[MBXNAME] = '\0';
  344.   
  345.             /* add a little test to avoid 'Mailfile busy' syndrome - WG7J
  346.              * Check for characters illegal in MS-DOS file names.
  347.              */
  348.                 for(cp = m->line;*cp != '\0';cp++)
  349.                     if(dosfnchr(*cp) == 0)
  350.                         break;
  351.                 if(*cp != '\0')
  352.                     continue;
  353.                 strcpy(m->name,m->line);
  354.                 tprintf("Password: %c%c%c",IAC,WILL,TN_ECHO);
  355.                 usflush(m->user);
  356.                 sockmode(m->user,SOCK_BINARY);
  357.                 if(mbxrecvline(m) == -1)
  358.                     return -1;
  359.                 tprintf("%c%c%c",IAC,WONT,TN_ECHO);
  360.                 sockmode(m->user,oldmode);
  361.                 tputc('\n');
  362.                 usflush(m->user);
  363.             /* This is needed if the password was send before the
  364.              * telnet no-echo options were receied. We neeed to
  365.              * flush the eold sequence from the input buffers, sigh
  366.              */
  367.                 if(socklen(m->user,0))/* discard any remaining input */
  368.                     recv_mbuf(m->user,NULL,0,NULLCHAR,0);
  369.                 if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,&anony))
  370.                 != -1){
  371.                     if(anony)
  372.                         log(m->user,"MBOX login: %s Password: %s",m->name,m->line);
  373.                     else
  374.                         log(m->user,"MBOX login: %s",m->name);
  375.                     if(m->privs & EXCLUDED_CMD)
  376.                         return -1;
  377. #ifdef AX25
  378.             /*try to set the name as the user-call.
  379.              *this is a very crude test! Be careful...
  380.              *Login must have at leat 1 digit (0-9) in it,
  381.              *and it must be possible to convert it to a call.
  382.              *if this doesn't work, disallow the gateway command,
  383.              *no matter if this was allowed by priviledges or not.
  384.              *Be careful, some one with login name '4us' and
  385.              *permission set to allow gateway/netrom, will
  386.              *go out as '4us-15' or '4us-0' !!!!!
  387.              *11/15/91 WG7J/PA3DIS
  388.              */
  389.                     for(cp=m->name;*cp != '\0';cp++)
  390.                         if(isdigit((int)*cp))
  391.                             break;
  392.                     if(*cp != '\0')
  393.                         founddigit = 1;
  394.                     if( (setcall(m->call,m->name) == -1) || (!founddigit) ) {
  395.                         m->privs &= ~AX25_CMD;
  396.                         m->privs &= ~NETROM_CMD;
  397.                     }
  398. #else
  399.                     m->privs &= ~AX25_CMD;
  400.                     m->privs &= ~NETROM_CMD;
  401.   
  402. #endif /* AX25 */
  403.             /* Set the morerows - WG7J */
  404.                     m->morerows = 20;
  405.                     return 0;
  406.                 }
  407.                 tputs("Login incorrect\n");
  408.                 log(m->user,"MBOX Login failed: %s, pw %s",m->name,m->line);
  409. #ifdef MAILERROR
  410.                 mail_error("MBOX Login failed: %s, pw %s",m->name,m->line);
  411. #endif
  412.                 *m->name = '\0';        /* wipe any garbage */
  413.             }
  414.     }
  415.     return 0;
  416. }
  417.   
  418. /* put up the prompt */
  419. void
  420. putprompt(m)
  421. struct mbx *m;
  422. {
  423.     char area[64];
  424.     char *cp1,*cp2;
  425.   
  426. #ifdef MAILCMDS
  427.     if(m->sid & MBX_SID)
  428.         tputs(">\n");
  429.     else {
  430. #endif
  431.         if(m->sid & MBX_NRID)
  432.             tputs(Mbnrid);
  433. #ifdef MAILCMDS
  434.         if(m->sid & MBX_AREA) {
  435.             cp1 = m->area;
  436.             cp2 = area;
  437.             /* Convert / and \ into . */
  438.             while(*cp1 != '\0') {
  439.                 if(*cp1=='/')
  440.                     *cp2 = '.';
  441.                 else
  442.                     *cp2 = *cp1;
  443.                 cp1++;
  444.                 cp2++;
  445.             }
  446.             *cp2 = '\0';
  447.             tprintf("Area: %s ",area);
  448.         }
  449. #endif
  450.         if(m->sid & MBX_EXPERT)
  451.             tputs(">\n");
  452.         else {
  453. #ifdef MAILCMDS
  454.             tprintf(MbCurrent,m->current);
  455. #endif
  456.             if(MbShowAliases && AliasList) {
  457.                 struct alias *a;
  458.   
  459.                 for(a=AliasList;a;a=a->next)
  460.                     tprintf("%s,",a->name);
  461.             }
  462.             tputs(Mbmenu);
  463.         }
  464.   
  465. #ifdef MAILCMDS
  466.     }
  467. #endif
  468. }
  469.   
  470. /* Incoming mailbox session */
  471. void
  472. mbx_incom(s,t,p)
  473. int s;
  474. void *t;
  475. void *p;
  476. {
  477.     struct tipcb *tip;
  478.     struct mbx *m,*mp,*pp;
  479.     struct usock *up;
  480.     struct alias *a;
  481.     char *buf[3];
  482.     char tmp[AXBUF];
  483.     int rval;
  484.     FILE *fp;
  485.     int newpriv = 0;
  486.   
  487. /*
  488.     if((up = itop(s)) != NULLUSOCK)
  489.     if(up->iface->flags & NO_AX25)
  490.  */
  491.   
  492.     sockmode(s,SOCK_ASCII);
  493.     sockowner(s,Curproc);   /* We own it now */
  494.     /* Secede from the parent's sockets, and use the network socket that
  495.      * was passed to us for both input and output. The reference
  496.      * count on this socket will still be 1; this allows the domboxbye()
  497.      * command to work by closing that socket with a single call.
  498.      * If we return, the socket will be closed automatically.
  499.      */
  500.     close_s(Curproc->output);
  501.     close_s(Curproc->input);
  502.     Curproc->output = Curproc->input = s;
  503.   
  504.     /* We'll do our own flushing right before we read input */
  505.     setflush(s,-1);
  506.   
  507.     if((m = newmbx()) == NULLMBX){
  508.         tputs("Too many mailbox sessions\n");
  509.         return;
  510.     }
  511.   
  512.     m->proc = Curproc;
  513.     m->user = s;
  514.     m->escape = 20;     /* default escape character is Ctrl-T */
  515.     m->type = (t == NULL) ? TELNET_LINK : (int) t;
  516.   
  517. #ifdef TIPSERVER
  518. #ifdef XMODEM
  519.     if(m->type == TIP_LINK) {
  520.         tip = (struct tipcb *) p;
  521.         tip->raw=0;
  522.         m->tip=tip;
  523.     }
  524. #endif
  525. #endif
  526.   
  527.     /* discard any remaining input */
  528.     /*
  529.     while(socklen(s,0))
  530.     recv_mbuf(s,NULL,0,NULLCHAR,0);
  531.     */
  532.   
  533.     /* get the name of the remote station */
  534.     if(mbx_getname(m) == -1) {
  535.         exitbbs(m);
  536.         return;
  537.     }
  538.     Totallogins++;
  539.     log(s,"MBOX open");
  540.   
  541. #ifdef RLOGINSERVER
  542.     if(m->type == RLOGIN_LINK) {
  543.        m->state = MBX_CMD;         /* start in command state */
  544.        tputc ('\n');
  545.        dosysop (1, (char **)0, (void *)m);
  546.        log(m->user, "MBOX exit: %s", m->name);     /* N5KNX: log exits */
  547.        exitbbs(m);
  548.        return;
  549.     }
  550. #endif
  551.  
  552.     if(m->privs & IS_BBS)
  553.         m->sid |= MBX_SID; /*force bbs status*/
  554.     else if(m->privs & IS_EXPERT)
  555.         m->sid |= MBX_EXPERT;
  556.   
  557.     loguser(m);
  558.     m->state = MBX_CMD;     /* start in command state */
  559. #ifdef MAILCMDS
  560.     tputs(MboxId);
  561. #endif
  562.   
  563.     /* Say 'hello' only if user is not a bbs - WG7J */
  564. #ifdef MAILCMDS
  565.     if(!(m->sid & MBX_SID+MBX_EXPERT)) {
  566. #endif
  567.   
  568. #ifdef USERLOG
  569.         tprintf(Mbwelcome,m->username ? m->username : m->name);
  570. #else
  571.         tprintf(Mbwelcome,m->name);
  572. #endif
  573.   
  574. #if defined AX25 || defined NETROM
  575.         if(m->family == AF_INET)
  576. #endif
  577.             tprintf(Mbbanner,Hostname,Version);
  578. #if defined AX25 || defined NETROM
  579.         else
  580.             tprintf(Mbbanner,pax25(tmp,Mycall),Version);
  581. #endif
  582.   
  583.         /* How many users are there currently ? */
  584.         tprintf(CurUsers,BbsUsers,BbsUsers == 1 ? "" : "s");
  585.   
  586. #ifdef MAILCMDS
  587.         /* Do we accept third party mail ? */
  588.         if(!ThirdParty)
  589.             tputs(Mbwarning);
  590. #endif
  591.         tputc('\n');
  592.   
  593.         /* Is there a message of the day ? */
  594.         if((fp = fopen(Motdfile,READ_TEXT)) != NULLFILE) {
  595.             sendfile(fp,m->user,ASCII_TYPE,0, m);
  596.             fclose(fp);
  597.         }
  598.   
  599. #ifdef MAILCMDS
  600.     }
  601.     if(!(m->sid & MBX_SID)) {
  602.         /* Enable our local message area,
  603.          * only if we're not a bbs - WG7J
  604.          */
  605.         buf[1] = m->name;
  606.         doarea(2,buf,m);
  607. #ifdef USERLOG
  608.         /* Tell about new arrived mail in message areas - WG7J */
  609.         if(Mbnewmail)
  610.             listnewmail(m,1);
  611.   
  612. #ifdef REGISTER
  613.         /* See if the username is empty. If so, the user hasn't
  614.          * registerd yet, so we need to beep and remind.
  615.          */
  616.         if(MbRegister && !m->username)
  617.             tprintf("\n\007Please type 'REGISTER' at the > prompt.\n");
  618. #endif /* REGISTER */
  619. #endif /* USERLOG */
  620.     }
  621. #endif /* MAILCMDS */
  622.   
  623.     /* Send prompt */
  624.     putprompt(m);
  625.   
  626.     /* now get commands */
  627.     while(mbxrecvline(m) != -1){
  628. #ifdef MAILCMDS
  629.         /* Only tell about new mail when in our own area - WG7J */
  630.         if(!(m->sid & MBX_SID)){
  631.             if(isnewprivmail(m) > 0L)
  632.                 newpriv = 1;
  633.             else
  634.                 newpriv = 0;
  635.             /* Do not check mailfile if we're bbs - WG7J*/
  636.             scanmail(m);
  637.         }
  638. #endif
  639.         /* check for an alias - WG7J */
  640.         if((a=findalias(m->line)) != NULL)
  641.             strcpy(m->line,a->cmd);
  642.   
  643.         if((rval = mbx_parse(m)) == -2)
  644.             break;
  645.         if(rval == 1)
  646.             tputs("Bad syntax.\n");
  647. #ifdef MAILCMDS
  648.         if(newpriv) {
  649.             tputs("You have new mail. ");
  650.             if(m->areatype != PRIVATE)
  651.                 tprintf("Change area with 'A %s'. ", m->name);
  652.             tputs("Please Kill when read!\n");
  653.         }
  654. #endif
  655.         putprompt(m);
  656.         m->state = MBX_CMD;
  657.     }
  658.     log(m->user, "MBOX exit: %s", m->name);    /* N5KNX: log exits */
  659.     exitbbs(m);
  660. }
  661.   
  662. void
  663. exitbbs(m)
  664. struct mbx *m;
  665. {
  666.     struct mbx *mp,*pp;
  667.     struct usock *up;
  668.   
  669.     /* Moving the socket close call to here
  670.      * will send a disconnect to the user before cleaning up
  671.      * the user's data structure. This gives a faster response perception
  672.      * to the user - WG7J
  673.      * N5KNX: but we must be careful to reset Curproc->{input,output} since
  674.      * otherwise killproc() will try again to close these sockets, and by
  675.      * then some other process may own it.  This sure is a kludge!
  676.      */
  677.     close_s(Curproc->output);
  678.     if (itop(Curproc->output) == NULLUSOCK) {
  679.         if (Curproc->input == Curproc->output) Curproc->input = -1;
  680.         Curproc->output = -1;
  681.     }
  682.   
  683.   
  684. #ifdef MAILCMDS
  685.     closenotes(m);
  686.     free(m->to);
  687.     free(m->tofrom);
  688.     free(m->origto);
  689.     free(m->origbbs);
  690.     free(m->subject);
  691.     free(m->date);
  692.     free(m->tomsgid);
  693. #endif
  694.     free(m->path);
  695.     free(m->startmsg);
  696. #ifdef USERLOG
  697.     free(m->username);
  698.     free(m->IPemail);
  699.     free(m->homebbs);
  700. #endif
  701. #ifdef MAILCMDS
  702.     /* Close the tempfiles if they are not nullpointers - WG7J */
  703.     if(m->tfile != (FILE *) 0)
  704.         fclose(m->tfile);
  705.     if(m->tfp != (FILE *) 0)
  706.         fclose(m->tfp);
  707.     if(m->mfile != (FILE *) 0)
  708.         fclose(m->mfile);
  709.     if(m->stdinbuf != NULLCHAR)
  710.         free(m->stdinbuf);
  711.     if(m->stdoutbuf != NULLCHAR)
  712.         free(m->stdoutbuf);
  713.     free((char *)m->mbox);
  714. #endif
  715.     /* now free it from list */
  716.     for(mp=Mbox,pp=NULLMBX;mp && mp!=m;pp=mp,mp=mp->next);
  717.     if(!mp)
  718.         /* what happened ??? */
  719.         return;
  720.     if(pp==NULLMBX)     /* first one on list */
  721.         Mbox = Mbox->next;
  722.     else
  723.         pp->next = m->next;
  724.     free((char *)m);
  725.     BbsUsers--;
  726. }
  727.   
  728. /**********************************************************************/
  729.   
  730. static struct cmds DFAR Mbcmds[] = {
  731. #ifdef MAILCMDS
  732.     "",             doreadnext,     0, 0, NULLCHAR,
  733. #endif
  734.     "?",            dombhelp,       0, 0, NULLCHAR,
  735. #ifdef MAILCMDS
  736.     "area",     doarea,     0, 0, NULLCHAR,
  737. #endif
  738.     "alias",    dombalias,  0, 0, NULLCHAR,
  739.     "bye",      domboxbye,  0, 0, NULLCHAR,
  740. #ifdef GATECMDS
  741. #if defined AX25 || defined NETROM
  742.     "connect",  dombconnect,0, 0, NULLCHAR,
  743. #endif
  744. #endif
  745. #ifdef CONVERS
  746.     "convers",  dombconvers,0, 0, NULLCHAR,
  747. #endif
  748. #ifdef FILECMDS
  749. #ifdef XMODEM
  750.     "download", dodownload, 0, 2, "D[U|X] <filename>",
  751. #else
  752.     "download", dodownload, 0, 2, "D[U] <filename>",
  753. #endif
  754. #endif
  755. #ifdef GATECMDS
  756.     "escape",       dombescape,     0, 0, NULLCHAR,
  757. #endif
  758. #ifdef FOQ_CMDS
  759.     "finger",       dombfinger,     0, 0, NULLCHAR,
  760. #endif
  761.     "help",         dombhelp,       0, 0, NULLCHAR,
  762.     "info",         dombhelp,       0, 0, NULLCHAR,
  763.     "iheard",   dombipheard,0, 0, NULLCHAR,
  764.     "iproute",  dombiproute,0, 0, NULLCHAR,
  765. #ifdef  AX25
  766.     "jheard",   dombjheard, 0, 0, NULLCHAR,
  767. #endif
  768. #ifdef MAILCMDS
  769.     "kill",     dodelmsg,   0, 0, NULLCHAR,
  770.     "list",     dolistnotes,0, 0, NULLCHAR,
  771. #endif
  772.     "mboxuser", dombusers,  0, 0, NULLCHAR,
  773. #if defined GATECMDS && defined NETROM
  774.     "nodes",    dombnrnodes,0, 0, NULLCHAR,
  775.     "nroutes",  dombnrneighbour, 0, 0, NULLCHAR,
  776. #endif
  777. #if defined FOQ_CMDS && defined TTYLINKSERVER
  778.     "operator", dochat,     0, 0, NULLCHAR,
  779. #endif
  780. #if defined GATECMDS && defined AX25
  781.     "ports",    dombports,  0, 0, NULLCHAR,
  782. #endif
  783. #ifdef GATECMDS
  784.     "ping",     dombping,   0, 2, "PI <host> [<len>] [<timeout>]",
  785. #endif
  786. #if defined FOQ_CMDS && defined CALLCLI
  787.     "query", dombcallbook, 0, 2, "Q callsign\nMultiple callsigns allowed per line",
  788. #endif
  789. #ifdef MAILCMDS
  790.     "read",     doreadmsg,  0, 0, NULLCHAR,
  791.     "send",         dosend,         0, 0, NULLCHAR,
  792. #if defined USERLOG && defined REGISTER
  793.     "register",     doregister,     0, 0, NULLCHAR,
  794. #endif
  795. #endif
  796. #ifdef GATECMDS
  797.     "telnet",   dombtelnet, 0, 2, "T hostname",
  798. #endif
  799. #ifdef FILECMDS
  800. #ifdef XMODEM
  801.     "upload",   dombupload, 0, 2, "U[U|X] <filename>",
  802. #else
  803.     "upload",   dombupload, 0, 2, "U[U] <filename>",
  804. #endif
  805. #endif
  806. #ifdef MAILCMDS
  807.     "verbose",  doreadmsg,  0, 0, NULLCHAR,
  808. #endif
  809. #ifdef FILECMDS
  810.     "what",     dowhat,     0, 0, NULLCHAR,
  811. #endif
  812.     "xpert",    dombexpert, 0, 0, NULLCHAR,
  813. #ifdef FILECMDS
  814.     "zap",      dozap,      0, 2, "Z filename",
  815. #endif
  816. #ifdef MAILCMDS
  817.     "[",        dosid,      0, 0, NULLCHAR,
  818. #ifdef MBFWD
  819.     "f>",       dorevfwd,   0, 0, NULLCHAR,
  820. #endif
  821. #endif
  822.     "@",        dosysop,    0, 0, NULLCHAR,
  823.     "***",      dostars,    0, 0, NULLCHAR,
  824.     ";",        dombsemicolon, 0, 0, NULLCHAR,
  825.     NULLCHAR,   NULLFP,     0, 0, "Huh?",
  826. };
  827.   
  828. /* "twocmds" defines the MBL/RLI two-letter commands, eg. "SB", "SP" and so on.
  829.  * They have to be treated specially since cmdparse() wants a space between
  830.  * the actual command and its arguments.
  831.  * "SP FOO" is converted to "s  foo" and the second command letter is saved
  832.  * in m->stype. Longer commands like "SEND" are unaffected, except for
  833.  * commands starting with "[", i.e. the SID, since we don't know what it will
  834.  * look like.
  835.  */
  836. static char twocmds[] =
  837. #ifdef MAILCMDS
  838. "aklrsv"
  839. #endif
  840. #ifdef FILECMDS
  841. "du"
  842. #endif
  843. "[mx";
  844.   
  845. int
  846. mbx_parse(m)
  847. struct mbx *m;
  848. {
  849.     char *cp;
  850.     int i;
  851.     char *newargv[2];
  852.   
  853.     /* Translate entire buffer to lower case */
  854.     for (cp = m->line; *cp != '\0'; ++cp)
  855.         if(isupper(*cp))
  856.             *cp = tolower(*cp);
  857.     /* Skip any spaces at the begining */
  858.     for(cp = m->line;isspace(*cp);++cp)
  859.         ;
  860.     m->stype = ' ';
  861.     if(*cp != '\0' && *(cp+1) != '\0') {
  862.         for(i=0; i<strlen(twocmds); ++i){
  863.             if(*cp == twocmds[i] && (isspace(*(cp+2)) || *(cp+2) == '\0'
  864.             || *cp == '[')){
  865.                 if(islower(*(++cp)))
  866.                     m->stype = toupper(*cp); /* Save the second character */
  867.                 else
  868.                     m->stype = *cp;
  869.                 *cp = ' ';
  870.                 break;
  871.             }
  872.         }
  873.     }
  874. #ifdef MAILCMDS
  875.     /* See if the input line consists solely of digits */
  876.     cp = m->line;
  877.     for(cp = m->line;isspace(*cp);++cp)
  878.         ;
  879.     newargv[1] = cp;
  880.     for(;*cp != '\0' && isdigit(*cp);++cp)
  881.         ;
  882.     if(*cp == '\0' && strlen(newargv[1]) > 0) {
  883.         newargv[0] = "r";
  884.         return doreadmsg(2,newargv,(void *)m);
  885.     } else
  886. #endif
  887.         return cmdparse(Mbcmds,m->line,(void *)m);
  888. }
  889.   
  890. /* This works like recvline(), but telnet options are answered and the
  891.  * terminating newline character is not put into the buffer. If the
  892.  * incoming character equals the value of escape, any queued input is
  893.  * flushed and -2 returned.
  894.  *
  895.  * mbxrecvline() now can gobble up suboptions - 94/02/14 VE4WTS
  896.  */
  897. int
  898. mbxrecvline(m)
  899. struct mbx *m;
  900. {
  901.     int s = m->user;
  902.     int escape = m->escape;
  903.     char *buf = m->line;
  904.     int c, cnt = 0, opt,cl;
  905.   
  906.     if(buf == NULLCHAR)
  907.         return 0;
  908.     usflush(Curproc->output);
  909.     alarm(Mbtdiscinit*1000L);   /* Start inactivity timeout - WG7J */
  910.     while((c = recvchar(s)) != EOF){
  911.         alarm(0L);
  912.         if(c == IAC){           /* Telnet command escape */
  913.             if((c = recvchar(s)) == EOF)
  914.                 break;
  915.             if(c >= 250 && c < 255 && (opt = recvchar(s)) != EOF){
  916.                 switch(c){
  917.                     case SB:
  918.                         opt=recvchar(s); /* Get the real option */
  919.                         if(opt==EOF)
  920.                             break;
  921.                         cl=opt;
  922.                         c=recvchar(s);
  923.                     /* Gobble up until we see IAC SE */
  924.                         while((c!=EOF) && !(cl==IAC && c==SE)){
  925.                         /* maybe check for timeout here, in case someone
  926.                            happened to send a binary file with the IAC SB
  927.                            sequence in it. */
  928.                             cl=c; /* keep track of second last char read */
  929.                             c=recvchar(s);
  930.                         }
  931.                     /* and tell the client where to go... */
  932.                     /* tprintf("%c%c%c",IAC,WONT,opt); */
  933.                         break;
  934.                     case WILL:
  935.                         if(opt==TN_LINEMODE){
  936.                         /* we WANT linemode */
  937.                             tprintf("%c%c%c",IAC,DO,opt);
  938.                         /* Tell client to do editing */
  939.                                 tprintf("%c%c%c%c%c%c%c",IAC,SB,TN_LINEMODE,1,1,IAC,SE);
  940.                         } else
  941.                             tprintf("%c%c%c",IAC,DONT,opt);
  942.                         break;
  943.                     case WONT:
  944.                         tprintf("%c%c%c",IAC,DONT,opt);
  945.                         break;
  946.                     case DO:
  947.                             tprintf("%c%c%c",IAC,WONT,opt);
  948.                             break;
  949.                     case DONT:
  950.                         tprintf("%c%c%c",IAC,WONT,opt);
  951.                 }
  952. /* to be fixed                  usflush(Curproc->output);*/
  953.                 continue;
  954.             }
  955.             if(c != IAC && (c = recvchar(s)) == EOF)
  956.                 break;
  957.         }
  958.         /* ordinary character */
  959.         if(c == '\r' || c == '\n')
  960.             break;
  961.         if(uchar(c) == escape){
  962.             if(socklen(s,0)) /* discard any remaining input */
  963.                 recv_mbuf(s,NULL,0,NULLCHAR,0);
  964.             cnt = -2;
  965.             break;
  966.         }
  967.         /* Handle <del> chars - from wa7tas */
  968.         if(c == 8 && cnt > 0) {
  969.             *--buf = 0;
  970.             cnt--;
  971.         } else {
  972.             *buf++ = c;
  973.             ++cnt;
  974.         }
  975.         if(cnt == MBXLINE - 1)
  976.             break;
  977.         alarm(Mbtdiscinit*1000L);   /* Restart inactivity timeout - WG7J */
  978.     }
  979.     if(c == EOF && cnt == 0)
  980.         return -1;
  981.     *buf = '\0';
  982.     return cnt;
  983. }
  984.   
  985. /* New forwarding option, simply ignore all data - WG7J */
  986. int
  987. dombsemicolon(int argc,char *argv[],void *p) {
  988.   
  989.     return 0;
  990. }
  991.   
  992. /* Determine what type of prompt is optimal, ie, can we read just one char? */
  993. int
  994. charmode_ok(m)
  995. struct mbx *m;
  996. {
  997.     if (m->type == TELNET_LINK || m->type == TIP_LINK) {
  998. #ifdef notdef
  999.         if ((up=itop(m->proc->output)) != NULLSOCK && up->type == TYPE_TCP) {
  1000.             up->cb.tcb->??? can't get to telnet->session->ttystate.echo
  1001.         }
  1002. #endif
  1003.         if (!(m->sid & MBX_LINEMODE)) return 1;   /* char mode OK (see XP cmd) */
  1004.     }
  1005.     return 0;
  1006. }
  1007.  
  1008.   
  1009. int
  1010. domboxbye(argc,argv,p)
  1011. int argc;
  1012. char *argv[];
  1013. void *p;
  1014. {
  1015.     struct mbx *m;
  1016.   
  1017.     m = (struct mbx *)p;
  1018.   
  1019.     /* for bbs's, just disconnect */
  1020.     if(m->sid & MBX_SID)
  1021.         return -2;
  1022.   
  1023. #ifdef USERLOG
  1024. #ifdef MAILCMDS
  1025.     setlastread(m);
  1026. #endif
  1027.     updatedefaults(m);
  1028. #endif
  1029.     /* Now say goodbye */
  1030.     if(!(m->privs & MBX_EXPERT))
  1031.         tprintf("\nThank you %s,\nfor calling %s JNOS.\n\n",
  1032. #ifdef USERLOG
  1033.         m->username ? m->username : m->name,
  1034. #else
  1035.         m->name,
  1036. #endif
  1037.         Hostname);
  1038. #ifdef TIPSERVER
  1039.     if(m->type == TIP_LINK)
  1040.         tputs("Please hang up now.\n");
  1041. #endif
  1042.     usflush(m->user);
  1043.     return -2;      /* signal that exitbbs() should be called */
  1044. }
  1045.   
  1046. static int
  1047. dombhelp(argc,argv,p)
  1048. int argc;
  1049. char *argv[];
  1050. void *p;
  1051. {
  1052.     char buf[255];
  1053.     int i;
  1054.     FILE *fp;
  1055.     struct mbx *m = (struct mbx *)p;
  1056.   
  1057.     if(*argv[0] == '?') {
  1058.         if(MbShowAliases && AliasList) {
  1059.             struct alias *a;
  1060.   
  1061.             tputs("Aliases:");
  1062.             for(a=AliasList;a;a=a->next)
  1063.                 tprintf(" %s",a->name);
  1064.             tputc('\n');
  1065.         }
  1066.         tputs(Longmenu);
  1067.         return 0;
  1068.     }
  1069.   
  1070.     buf[0] = '\0';
  1071.     if(argc > 1)
  1072.         for(i=0; Mbcmds[i].name != NULLCHAR; ++i)
  1073.             if(!strncmp(Mbcmds[i].name,argv[1],strlen(argv[1]))) {
  1074.                 sprintf(buf,"%s/%s.hlp",Helpdir,Mbcmds[i].name);
  1075.                 break;
  1076.             }
  1077.     if(buf[0] == '\0')
  1078.         if(*argv[0] == 'i') {
  1079.             /* INFO command */
  1080.             tprintf(Nosversion,Version);
  1081.             sprintf(buf,"%s/info.hlp",Helpdir);
  1082.         } else
  1083.             sprintf(buf,"%s/help.hlp",Helpdir);
  1084.   
  1085.     if((fp = fopen(buf,READ_TEXT)) != NULLFILE) {
  1086.         sendfile(fp,Curproc->output,ASCII_TYPE,0,m);
  1087.         fclose(fp);
  1088.     } else {
  1089.         if(*argv[0]!='i')
  1090.             tputs("No help available.\n");
  1091.     }
  1092.     return 0;
  1093. }
  1094.   
  1095. extern void dumproute __ARGS((struct route *rp,char *p));
  1096. extern char RouteHeader[];
  1097.   
  1098. /* Show non-private routes only */
  1099. int
  1100. dombiproute(argc,argv,p)
  1101. int argc;
  1102. char *argv[];
  1103. void *p;
  1104. {
  1105.     int i,bits;
  1106.     struct route *rp;
  1107.     struct mbx *m = (struct mbx *)p;
  1108.     char buf[85];
  1109.   
  1110.     if(m->privs & NO_LISTS) {
  1111.         tputs(Noperm);
  1112.         return 0;
  1113.     }
  1114.   
  1115.     tputs(RouteHeader);
  1116.     for(bits=31;bits>=0;bits--){
  1117.         for(i=0;i<HASHMOD;i++){
  1118.             for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
  1119.                 if(!(rp->flags & RTPRIVATE)) {
  1120.                     dumproute(rp,buf);
  1121.                     if(tprintf("%s\n",&buf[4]) == EOF)
  1122.                         return 0;
  1123.                 }
  1124.             }
  1125.         }
  1126.     }
  1127.     if(R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)) {
  1128.         dumproute(&R_default,buf);
  1129.         if(tprintf("%s\n",&buf[4]) == EOF)
  1130.             return 0;
  1131.     }
  1132.     return 0;
  1133. }
  1134.   
  1135.   
  1136. static int
  1137. dombexpert(argc,argv,p)
  1138. int argc;
  1139. char *argv[];
  1140. void *p;
  1141. {
  1142.     struct mbx *m;
  1143.   
  1144.     m = (struct mbx *)p;
  1145.   
  1146.     switch(m->stype) {
  1147.         case 'M':
  1148.             if(argc == 1)
  1149.                 tprintf("-more- after %d lines\n",m->morerows);
  1150.             else {
  1151.                 m->morerows = atoi(argv[1]);
  1152.             }
  1153.             break;
  1154.         case 'A':
  1155.             m->sid ^= MBX_AREA;
  1156.             break;
  1157.         case 'N':
  1158.             m->sid ^= MBX_NRID;
  1159.             break;
  1160.         case 'P':
  1161.             m->sid ^= MBX_LINEMODE;
  1162.             tprintf("LINEMODE is now %sabled\n", m->sid&MBX_LINEMODE ? "en" : "dis");
  1163.             break;
  1164.   
  1165. #if defined USERLOG && defined REGISTER
  1166.         case 'R':
  1167.             if(argc > 1) {
  1168.             /* Change the state of the 'Reply-to' header */
  1169.                 if(!stricmp(argv[1],"on"))
  1170.                     m->sid |= MBX_REPLYADDR;
  1171.                 else if(!stricmp(argv[1],"off"))
  1172.                     m->sid &= ~MBX_REPLYADDR;
  1173.             }
  1174.             tprintf("'Reply-to: %s' header is %sadded when sending mail.\n",
  1175.             ( m->IPemail ?
  1176.             ((m->sid & MBX_REPLYADDR) ? m->IPemail : "") :
  1177.             "" ),
  1178.             (m->sid & MBX_REPLYADDR) ? "" : "not " );
  1179.             if((m->sid & MBX_REPLYADDR) && !m->IPemail)
  1180.                 tprintf("Please 'register' to set your email reply-to address!\n");
  1181.             break;
  1182. #endif
  1183.   
  1184.         default:
  1185.             m->sid ^= MBX_EXPERT;
  1186.             break;
  1187.     }
  1188.     return 0;
  1189. }
  1190.   
  1191. #if defined FOQ_CMDS && defined TTYLINKSERVER
  1192. extern char SysopBusy[];
  1193.   
  1194. static int
  1195. dochat(argc,argv,p)
  1196. int argc;
  1197. char *argv[];
  1198. void *p;
  1199. {
  1200.     char buf[8], *newargv[3];
  1201.     struct mbx *m;
  1202.   
  1203.     m = (struct mbx *)p;
  1204.   
  1205.     if (MAttended) {
  1206.         m->state = MBX_CHAT;
  1207.         newargv[0] = "C";
  1208.         newargv[1] = Hostname;
  1209.         sprintf(buf,"%d",IPPORT_TTYLINK);
  1210.         newargv[2] = buf;
  1211.         m->startmsg = mallocw(50);
  1212.         sprintf(m->startmsg,"*** MBOX Chat with %s\n",m->name);
  1213.         return dombtelnet(3,newargv,p);
  1214.     } else {
  1215.         tputs(SysopBusy);
  1216.     }
  1217.     /* It returns only after a disconnect or refusal */
  1218.     return 0;
  1219. }
  1220. #endif /* TTYLINKSERVER */
  1221.   
  1222. static int
  1223. dombipheard(argc,argv,p)
  1224. int argc;
  1225. char *argv[];
  1226. void *p;
  1227. {
  1228.     struct mbx *m = (struct mbx *)p;
  1229.   
  1230.     if(m->privs & NO_LISTS) {
  1231.         tputs(Noperm);
  1232.         return 0;
  1233.     }
  1234.     return doipheard(argc,argv,NULL);
  1235. }
  1236.   
  1237. #ifdef AX25
  1238. static int
  1239. dombjheard(argc,argv,p)
  1240. int argc;
  1241. char *argv[];
  1242. void *p;
  1243. {
  1244.     struct iface *ifp;
  1245.     struct mbx *m = (struct mbx *)p;
  1246.   
  1247.     if(m->privs & NO_LISTS) {
  1248.         tputs(Noperm);
  1249.         return 0;
  1250.     }
  1251.   
  1252.     if(argc > 1){
  1253.         if( ((ifp = if_lookup(argv[1])) == NULLIF) || (ifp->type != CL_AX25) ||
  1254.         ((ifp->flags & HIDE_PORT) && !(m->privs & MBX_SYSOP)) ) {
  1255.             tprintf(Badinterface,argv[1]);
  1256.             return 0;
  1257.         }
  1258.         axheard(ifp);
  1259.         return 0;
  1260.     }
  1261.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  1262.         if((ifp->flags & LOG_AXHEARD)  && ( !(ifp->flags & HIDE_PORT) || m->privs&MBX_SYSOP) )
  1263.             if(axheard(ifp) == EOF)
  1264.                 break;
  1265.     }
  1266.     return 0;
  1267. }
  1268. #endif
  1269.   
  1270. #if defined FOQ_CMDS && defined CALLCLI
  1271. static int
  1272. dombcallbook(argc,argv,p)
  1273. int argc;
  1274. char *argv[];
  1275. void *p;
  1276. {
  1277.     struct mbx *m;
  1278.     char buf[8], *newargv[3];
  1279.     extern char *Callserver;
  1280.     int req, ret = 0;
  1281.   
  1282.     m = (struct mbx *) p;
  1283.   
  1284.     sprintf(buf,"%d",IPPORT_CALLDB);
  1285.     newargv[0] = "Q";
  1286.     newargv[1] = Callserver;
  1287.     newargv[2] = buf;
  1288.   
  1289.     for (req = 1; req < argc; req++)  {
  1290.         if(argv[req] == NULLCHAR)
  1291.             return ret;
  1292.         m->startmsg = mallocw(80);  /* is freed each time by gw_connect()         */
  1293.         sprintf(m->startmsg,"%s\n", argv[req]);
  1294.         log(m->user, "MBOX callbook %s: %s",m->name,argv[req]);
  1295.         tprintf("Looking for \" %s \" in the callbook at %s\n",argv[req],Callserver);
  1296.         ret = dombtelnet(3,newargv,p);
  1297.     }
  1298.     return ret; /* It looks like all possible returns are zero anyway!    */
  1299. }
  1300. #endif /* CALLCLI */
  1301.   
  1302. /*Password protection added - 920118, WG7J */
  1303. int
  1304. dosysop(argc,argv,p)
  1305. int argc;
  1306. char *argv[];
  1307. void *p;
  1308. {
  1309.     struct mbx *m;
  1310.     int c;
  1311.     int len,pwdc[5],i,valid=0;
  1312.     char *cp;
  1313.     extern struct cmds DFAR Cmds[];
  1314.   
  1315.     m = (struct mbx *) p;
  1316.     log(m->user,"MBOX: %s attempting SYSOP",m->name);
  1317.   
  1318.     /*If you want anyone with the password to go sysop-mode
  1319.      *comment out the next 4 line ! -WG7J
  1320.      */
  1321.     if(!(m->privs & SYSOP_CMD)){
  1322.         tputs(Noperm);
  1323. #ifdef MAILERROR
  1324.         mail_error("%s: SYSOP denied!\n",m->name);
  1325. #endif
  1326.         return 0;
  1327.     }
  1328.   
  1329.     /*only if set,
  1330.      *check for the password before letting users proceed
  1331.      */
  1332.     m->state = MBX_SYSOPTRY;
  1333.     if((len = strlen(Mbpasswd)) != 0) {;
  1334.         for (i=0;i<5;i++)
  1335.             tprintf("%d ",(pwdc[i]=RANDOM(len))); /*print the random chars*/
  1336.         tputc('\n');
  1337.         while(1) {
  1338.             c = mbxrecvline(m);
  1339.             if(c == EOF || c == -2)
  1340.                 return 0;
  1341.             if(*m->line == '\0')
  1342.                 break;
  1343.             cp = m->line;
  1344.             for(i=0;i<5;i++)
  1345.                 if(*cp++ != Mbpasswd[pwdc[i]])
  1346.                     break;
  1347.             if (i == 5)
  1348.                 valid = 1;
  1349.         }
  1350.         if(!valid)
  1351.             return 0;
  1352.     }
  1353.   
  1354.     log(m->user,"MBOX: %s is now SYSOP",m->name);
  1355.     m->state = MBX_SYSOP;
  1356.     tputs("\n\aType 'exit' to return\n");
  1357.   
  1358.     for(;;){
  1359.         tprintf("%lu Jnos> ",coreleft());
  1360.         usflush(Curproc->output);
  1361.         if(mbxrecvline(m) < 0)
  1362.             break;
  1363.         log(m->user,"MBOX sysop: %s",m->line);
  1364.         if(cmdparse(Cmds,m->line,NULL) == -2)
  1365.             break;
  1366.     }
  1367.     return 0;
  1368. }
  1369.   
  1370. /* Handle the "*** Done" command when reverse forwarding ends or the
  1371.  * "*** LINKED to" command.
  1372.  */
  1373. int
  1374. dostars(argc,argv,p)
  1375. int argc;
  1376. char *argv[];
  1377. void *p;
  1378. {
  1379.     struct mbx *m;
  1380.     int anony = 1;
  1381.     int founddigit = 0;
  1382.     long oldprivs;
  1383.     char *cp;
  1384.   
  1385.     m = (struct mbx *)p;
  1386.   
  1387.     /* Allow 'linked to' from anyone, but reset SYSOP priviledges
  1388.      * when the sysop-password is not set !
  1389.      * Also try to set the new call !
  1390.      * Inspired by Kurt, wb5bbw
  1391.      * Check for the strange TEXNET linked message !
  1392.      * 920220 - WG7J
  1393.      */
  1394.     if((argc >= 4) && !strcmp(argv[1],"linked") && !strcmp(argv[2],"to")) {
  1395.         if(m->privs & NO_LINKEDTO) {
  1396.             puts(Noperm);
  1397. #ifdef GWTRACE
  1398.             log(m->user,"MBOX LINKED: %s permission denied",m->name);
  1399. #endif
  1400.             return 0;
  1401.         }
  1402. #ifdef GWTRACE
  1403.         log(m->user,"MBOX LINKED: %s changed to %s",m->name,argv[3]);
  1404. #endif
  1405. #ifdef USERLOG
  1406. #ifdef MAILCMDS
  1407.         setlastread(m);
  1408. #endif
  1409.         updatedefaults(m);
  1410. #endif
  1411.         strcpy(m->name,argv[3]);
  1412.         oldprivs = m->privs; /*Save this !*/
  1413.         /* Try to find the privileges of this user from the userfile */
  1414.         if((m->privs = userlogin(m->name,NULLCHAR,&m->path,MBXLINE,
  1415.             &anony)) == -1)
  1416.             if((m->privs = userlogin("bbs",NULLCHAR,&m->path,
  1417.                 MBXLINE,&anony)) == -1)
  1418.                 if((m->privs = userlogin("anonymous",NULLCHAR,
  1419.                 &m->path,MBXLINE,&anony)) == -1){
  1420.                     m->privs = 0;
  1421.                     free(m->path);
  1422.                     m->path = NULLCHAR;
  1423.                 }
  1424.         if(m->privs & EXCLUDED_CMD)
  1425.             return domboxbye(0,NULLCHARP,p);
  1426. #ifdef AX25
  1427.     /* Set the call */
  1428.         for(cp=m->name;*cp != '\0';cp++)
  1429.             if(isdigit((int)*cp))
  1430.                 break;
  1431.         if(*cp != '\0')
  1432.             founddigit = 1;
  1433.         if( (setcall(m->call,m->name) == -1) || (!founddigit) ) {
  1434.             m->privs &= ~AX25_CMD;
  1435.             m->privs &= ~NETROM_CMD;
  1436.         }
  1437. #else
  1438.         m->privs &= ~AX25_CMD;
  1439.         m->privs &= ~NETROM_CMD;
  1440. #endif
  1441.         /*Kill ssid in name, if any*/
  1442.         if((cp=strchr(m->name,'-')) != NULLCHAR)
  1443.             *cp = '\0';
  1444.         /* Check if sysop password is set,
  1445.          * if not, disallow sysop privs no matter what !
  1446.          */
  1447.         if(*Mbpasswd == '\0')
  1448.             m->privs &= ~SYSOP_CMD;
  1449.         /* Check to see if any of NO_READ,NO_SEND or NO_3PARTY were set,
  1450.          * if so, dis-allow those no matter what
  1451.          * (so that users cannot get priviledges by issuing a ***linked)
  1452.          * 920220 - WG7J
  1453.          */
  1454.         if(oldprivs & NO_SENDCMD)
  1455.             m->privs |= NO_SENDCMD;
  1456.         if(oldprivs & NO_READCMD)
  1457.             m->privs |= NO_READCMD;
  1458.         if(oldprivs & NO_3PARTY)
  1459.             m->privs |= NO_3PARTY;
  1460.         if(oldprivs & NO_CONVERS)
  1461.             m->privs |= NO_CONVERS;
  1462.         if(oldprivs & NO_LISTS)
  1463.             m->privs |= NO_LISTS;
  1464.   
  1465.         /* Log this new user in */
  1466.         loguser(m);
  1467.   
  1468. #ifdef USERLOG
  1469.         tprintf("Oh, hello %s.\n",m->username ? m->username : m->name);
  1470. #else
  1471.         tprintf("Oh, hello %s.\n",m->name);
  1472. #endif
  1473.   
  1474. #ifdef MAILCMDS
  1475.         changearea(m,m->name);
  1476. #endif
  1477.         return 0;
  1478.     }
  1479.   
  1480.     if(argc > 1 && (m->sid & MBX_SID))      /* "*** Done" or similar */
  1481.         return -2;
  1482.     return -1;
  1483. }
  1484.   
  1485. #ifdef FOQ_CMDS
  1486. int
  1487. dombfinger(argc,argv,p)
  1488. int argc;
  1489. char *argv[];
  1490. void *p;
  1491. {
  1492.     struct mbx *m;
  1493.     char *host, *user = NULLCHAR, buf[8], *newargv[3];
  1494.   
  1495.     if(argc > 2){
  1496.         tputs("Usage: F user@host  or  F @host  or  F user.\n");
  1497.         return 0;
  1498.     }
  1499.     host = Hostname;
  1500.     if(argc == 2){
  1501.         if((host = strchr(argv[1], '@')) != NULLCHAR){
  1502.             *host = '\0';
  1503.             host++;
  1504.         } else
  1505.             host = Hostname;
  1506.         user = argv[1];
  1507.     }
  1508.     m = (struct mbx *) p;
  1509.     m->startmsg = mallocw(80);
  1510.     if(user != NULLCHAR)
  1511.         sprintf(m->startmsg,"%s\n",user);
  1512.     else
  1513.         strcpy(m->startmsg,"\n");
  1514.     newargv[0] = "";
  1515.     newargv[1] = host;
  1516.     sprintf(buf,"%d",IPPORT_FINGER);
  1517.     newargv[2] = buf;
  1518.     return dombtelnet(3,newargv,p);
  1519. }
  1520. #endif /* FOQ_CMDS */
  1521.   
  1522. #ifdef  CONVERS
  1523. extern int Mbconverse;
  1524. extern int CDefaultChannel;
  1525.   
  1526. int
  1527. dombconvers(argc,argv,p)
  1528. int argc;
  1529. char *argv[];
  1530. void *p;
  1531. {
  1532.     struct mbx *m = (struct mbx *)p;
  1533.     int channel = 0;
  1534.   
  1535.     if(m->privs & NO_CONVERS) {
  1536.         tputs(Noperm);
  1537. #ifdef MAILERROR
  1538.         mail_error("%s: converse denied\n",m->name);
  1539. #endif
  1540.         return 0;
  1541.     }
  1542.     if(!Mbconverse) {
  1543.         tputs("Mailbox Convers server not enabled\n");
  1544.         return 0;
  1545.     }
  1546.     m->state = MBX_CONVERS;
  1547.     if(argc > 1)
  1548.         channel = atoi(argv[1]);
  1549.     else
  1550.         channel = CDefaultChannel;
  1551. #ifdef GWTRACE
  1552.     log(m->user,"MBOX CONVERS: %s",m->name);
  1553. #endif
  1554.     mbox_converse(m,channel);
  1555.     return 0;
  1556. }
  1557. #endif /* CONVERS */
  1558.   
  1559. #endif /* MAILBOX */
  1560.